
#include once "math/vecf.bi"
#include once "math/matrix4x4f.bi"

constructor vec3f ( byval x as single, byval y as single, byval z as single )

	this.x = x
	this.y = y
	this.z = z

end constructor


constructor vec3f ( byref v3d as vec3f )

	this.x = v3d.x
	this.y = v3d.y
	this.z = v3d.z

end constructor


constructor vec3f ( )

	this.x = 0.0
	this.y = 0.0
	this.z = 0.0

end constructor


function vec3f.dot ( byref v As vec3f ) as MATH_PRECISION
    
    Return  this.x * v.x + this.y * v.y + this.z * v.z
    
end function


function vec3f.magnitude( ) As MATH_PRECISION
    
     Dim Mag As MATH_PRECISION = any
     mag = Sqr( this.x ^2 + this.y ^2 + this.z ^2 )
     If mag = 0 Then mag = 1
     return mag
     
end function


sub vec3f.normalize()
    
	this = this / this.magnitude()
	
end sub


function vec3f.UnitVec() as vec3f
    
	 return this / this.magnitude()
	
end function


function vec3f.cross( byref v as vec3f ) as vec3f
    
	return Type<vec3f>((this.y * v.z) - (v.y * this.z), (this.z * v.x) - (v.z * this.x), (this.x * v.y) - (v.x * this.y))
	
end function


function vec3f.distance( byref v as vec3f ) as MATH_PRECISION
    
	return Sqr((v.x - this.x)^2 + (v.y - this.y)^2 + (v.z - this.z)^2)
	
end function


function vec3f.AngleBetween( byref v As vec3f ) As MATH_PRECISION
    
    return acos( this.dot(v) / (this.magnitude * v.magnitude) )
    
end function


operator vec3f.cast() as string
    
	return "x: " & this.x & ", y: " & this.y & ", z: " & this.z
	
end operator


operator vec3f.cast() as vec2f
    
	return type<vec2f>(this.x, this.y)
	
end operator


operator + ( Byref lhs As vec3f, Byref rhs As Single ) As vec3f
    
    Return Type<vec3f>( lhs.x + rhs, lhs.y + rhs,  lhs.z + rhs )
    
End operator


operator + ( Byref lhs As vec3f, Byref rhs As vec3f ) As vec3f
    
    Return Type<vec3f>( lhs.x + rhs.x, lhs.y + rhs.y,  lhs.z + rhs.z )
    
End operator


operator - ( Byref lhs As vec3f ) As vec3f
 
    Return Type<vec3f>(-lhs.x, -lhs.y, -lhs.z )
 
End operator 
 
 
operator - ( Byref lhs As vec3f, Byref rhs As vec3f ) As vec3f
 
    Return Type<vec3f>(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z )
 
End operator


operator - ( Byref lhs As vec3f, Byref rhs As vec4f ) As vec3f
 
    Return Type<vec3f>(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z )
 
End operator
 
 
operator - ( Byref lhs As vec3f, Byref rhs As Single ) As vec3f
 
    Return Type<vec3f>(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs )
 
End operator
 
 
operator * ( Byref lhs As vec3f, Byref rhs As vec3f ) As vec3f
 
    Return Type<vec3f>(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z )
 
End operator


operator * ( Byref lhs As vec3f, Byref rhs As vec4f ) As vec3f
 
    Return Type<vec3f>(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z )
 
End operator


operator * ( Byref lhs As vec3f, Byref rhs As Double ) As vec3f
    
    Return Type<vec3f>(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs )
    
End operator
 
 
operator * ( Byref lhs As vec3f, Byref rhs As Single ) As vec3f
    
    Return Type<vec3f>(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs )
    
End operator


operator vec3f.*= ( byref rhs as matrix_ )

	this = this * rhs
	
end operator


operator vec3f.*= ( Byref s As single )
    
    this.x *= s
    this.y *= s
    this.z *= s
    
End operator


operator vec3f.+=( byref rhs As vec3f )
    
    this.x += rhs.x
    this.y += rhs.y
    this.z += rhs.z
    
end operator


operator / ( Byref lhs As vec3f, Byref rhs As vec3f ) As vec3f
    
    Return Type<vec3f>(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z )
     
End operator


operator / ( Byref lhs As vec3f, Byref rhs As Single ) As vec3f
    
    Return Type<vec3f>(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs )
     
End operator


operator / ( Byref lhs As vec3f, Byref rhs As Double ) As vec3f
    
    Return Type<vec3f>(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs )
     
End operator
